import {
    AIConfig,
    ModelTag,
    ModelListResponse,
    ModelInfo,
    ModelInfoCache,
} from "../types/ollama";
import { proxyFetch } from "../../util/proxy";

const CONFIG_KEY = "aiConfig";
const DEFAULT_BASE_URL = "http://127.0.0.1:11434";
const DEFAULT_VENDOR = "ollama";

const defaultConfig: AIConfig = {
    provider: DEFAULT_VENDOR,
    baseUrl: DEFAULT_BASE_URL,
    selectedModel: "",
};

export class ConfigService {
    private static instance: ConfigService;
    private config: AIConfig;
    private modelInfoCache: ModelInfoCache;

    private constructor() {
        this.config = this.loadConfig();
        this.modelInfoCache = {};
    }

    public static getInstance(): ConfigService {
        if (!ConfigService.instance) {
            ConfigService.instance = new ConfigService();
        }
        return ConfigService.instance;
    }

    private loadConfig(): AIConfig {
        const savedConfig = localStorage.getItem(CONFIG_KEY);
        if (savedConfig) {
            try {
                return JSON.parse(savedConfig);
            } catch (e) {
                console.error("Failed to parse saved config:", e);
            }
        }
        return { ...defaultConfig };
    }

    public getConfig(): AIConfig {
        return { ...this.config };
    }

    public async saveConfig(newConfig: AIConfig): Promise<void> {
        this.config = { ...newConfig };
        localStorage.setItem(CONFIG_KEY, JSON.stringify(this.config));
    }

    public async getModels(): Promise<ModelListResponse["models"]> {
        try {
            const response = await proxyFetch(
                `${this.config.baseUrl}/api/tags`,
            );
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            const data: ModelListResponse = await response.json();
            return data.models;
        } catch (error) {
            console.error("Failed to fetch models:", error);
            throw error;
        }
    }

    /**
     * 解析类似配置文件的字符串为对象
     * @param str - 配置字符串
     * @returns 解析后的对象
     */
    public parseConfigString(str: string | undefined): Record<string, any> {
        if (typeof str !== "string") {
            return {};
        }
        const result: Record<string, any> = {};
        const lines = str.split("\n");
        lines.forEach((line) => {
            // 去除前后空白字符
            const trimmedLine = line.trim();
            // 跳过空行和注释
            if (trimmedLine === "" || trimmedLine.startsWith("#")) {
                return;
            }
            // 分割键值对
            const [key, value] = trimmedLine.split(/\s+/);
            if (key !== undefined && value !== undefined) {
                // 尝试将值解析为数字或布尔值
                let parsedValue: any = value;
                if (value.toLowerCase() === "true") {
                    parsedValue = true;
                } else if (value.toLowerCase() === "false") {
                    parsedValue = false;
                } else if (!isNaN(Number(value))) {
                    parsedValue = Number(value);
                } else if (value.startsWith('"') && value.endsWith('"')) {
                    parsedValue = value.slice(1, -1);
                }
                result[key] = parsedValue;
            }
        });
        return result;
    }

    public async getModelInfo(modelName: string): Promise<ModelInfo | null> {
        if (!modelName) {
            return null;
        }
        // 检查缓存中是否存在
        const cachedInfo = this.modelInfoCache[modelName];
        if (cachedInfo) {
            return cachedInfo;
        }

        return (this.modelInfoCache[modelName] = (async () => {
            console.log("fetch model info: ", modelName);
            try {
                const response = await proxyFetch(
                    `${this.config.baseUrl}/api/show`,
                    {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify({ name: modelName }),
                    },
                );

                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }

                const data = await response.json();
                data.name = data.name || modelName;
                // 将非空结果存入缓存
                this.modelInfoCache[modelName] = data;
                return data;
            } catch (error) {
                this.modelInfoCache[modelName] = null;
                console.error(
                    `Failed to fetch model info for ${modelName}:`,
                    error,
                );
                return null;
            }
        })());
    }
}
